using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WPFTemplateLib.Controls.Panels
{
	/// <summary>
	/// [GitHub Copilot] 仅在 OnRender 中绘制分隔线的 StackPanel，不修改 Children，适用于作为 ItemsPanel 使用。
	/// <para/>如果发现有线条消失或粗细设置没反应，优先检查是否存在被遮挡的情况，或可尝试使用 <see cref="AdornerSeparatorStackPanel"/>。
	/// </summary>
	public class RenderedSeparatorStackPanel : StackPanel
	{
		#region 构造

		public RenderedSeparatorStackPanel()
		{
			// 有助于像素对齐
			SnapsToDevicePixels = true;
		}

		#endregion

		#region 依赖属性

		public static readonly DependencyProperty IsShowSeparatorProperty = DependencyProperty.Register(
			nameof(IsShowSeparator), typeof(bool), typeof(RenderedSeparatorStackPanel),
			new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
		/// <summary>
		/// 是否显示分隔线（默认 true）
		/// </summary>
		public bool IsShowSeparator
		{
			get => (bool)GetValue(IsShowSeparatorProperty);
			set => SetValue(IsShowSeparatorProperty, value);
		}

		public static readonly DependencyProperty SeparatorBrushProperty = DependencyProperty.Register(
			nameof(SeparatorBrush), typeof(Brush), typeof(RenderedSeparatorStackPanel),
			new FrameworkPropertyMetadata(Brushes.LightGray, FrameworkPropertyMetadataOptions.AffectsRender));
		/// <summary>
		/// 分隔线画刷
		/// </summary>
		public Brush SeparatorBrush
		{
			get => (Brush)GetValue(SeparatorBrushProperty);
			set => SetValue(SeparatorBrushProperty, value);
		}

		public static readonly DependencyProperty SeparatorThicknessProperty = DependencyProperty.Register(
			nameof(SeparatorThickness), typeof(double), typeof(RenderedSeparatorStackPanel),
			new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
		/// <summary>
		/// 分隔线粗细（DIP，设备无关像素）
		/// </summary>
		public double SeparatorThickness
		{
			get => (double)GetValue(SeparatorThicknessProperty);
			set => SetValue(SeparatorThicknessProperty, value);
		}

		public static readonly DependencyProperty SeparatorInsetProperty = DependencyProperty.Register(
			nameof(SeparatorInset), typeof(double), typeof(RenderedSeparatorStackPanel),
			new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
		/// <summary>
		/// 分隔线两端缩进（水平时为上下内缩，垂直时为左右内缩）
		/// </summary>
		public double SeparatorInset
		{
			get => (double)GetValue(SeparatorInsetProperty);
			set => SetValue(SeparatorInsetProperty, value);
		}

		#endregion

		#region 渲染

		protected override void OnRender(DrawingContext dc)
		{
			base.OnRender(dc);

			if (!IsShowSeparator || SeparatorBrush == null) return;

			int count = InternalChildren?.Count ?? 0;
			if (count < 2) return;

			if (SeparatorThickness <= 0) return;

			var dpi = VisualTreeHelper.GetDpi(this);

			if (Orientation == Orientation.Horizontal)
			{
				// 垂直分隔线：直接使用 DIP 粗细；仅对坐标做像素/半像素对齐
				var pen = new Pen(SeparatorBrush, SeparatorThickness);
				if (pen.CanFreeze) pen.Freeze();

				// 计算当前粗细对应的物理像素宽度，用于奇偶像素时的 0.5 偏移以居中
				double pixelThickness = SeparatorThickness * dpi.DpiScaleX;
				bool isOddPx = ((int)Math.Round(pixelThickness)) % 2 == 1;

				for (int i = 0; i < count - 1; i++)
				{
					var child = InternalChildren[i] as UIElement;
					if (child == null || child.Visibility != Visibility.Visible) continue;

					// 子元素右边界 X（DIP） + 其 Margin.Right
					double x = child.TranslatePoint(new Point(child.RenderSize.Width, 0), this).X;
					double marginRight = 0;
					if (child is FrameworkElement feH) marginRight = feH.Margin.Right;
					x += marginRight; // 加上边距，使分隔线绘制在“元素边缘+边距”位置

					// 对齐到最接近的像素，并在奇数像素粗细时增加半像素偏移以居中
					double xPixels = Math.Round(x * dpi.DpiScaleX) + (isOddPx ? 0.5 : 0.0);
					double xAligned = xPixels / dpi.DpiScaleX;

					double y1 = SeparatorInset;
					double y2 = Math.Max(0, ActualHeight - SeparatorInset);

					var guidelines = new GuidelineSet();
					guidelines.GuidelinesX.Add(xAligned);
					dc.PushGuidelineSet(guidelines);
					dc.DrawLine(pen, new Point(xAligned, y1), new Point(xAligned, y2));
					dc.Pop();
				}
			}
			else // Vertical
			{
				// 水平分隔线：直接使用 DIP 粗细；仅对坐标做像素/半像素对齐
				var pen = new Pen(SeparatorBrush, SeparatorThickness);
				if (pen.CanFreeze) pen.Freeze();

				double pixelThickness = SeparatorThickness * dpi.DpiScaleY;
				bool isOddPx = ((int)Math.Round(pixelThickness)) % 2 == 1;

				for (int i = 0; i < count - 1; i++)
				{
					var child = InternalChildren[i] as UIElement;
					if (child == null || child.Visibility != Visibility.Visible) continue;

					// 子元素下边界 Y（DIP） + 其 Margin.Bottom
					double y = child.TranslatePoint(new Point(0, child.RenderSize.Height), this).Y;
					double marginBottom = 0;
					if (child is FrameworkElement feV) marginBottom = feV.Margin.Bottom;
					y += marginBottom; // 加上边距，使分隔线绘制在“元素边缘+边距”位置

					// 对齐到最接近的像素，并在奇数像素粗细时增加半像素偏移以居中
					double yPixels = Math.Round(y * dpi.DpiScaleY) + (isOddPx ? 0.5 : 0.0);
					double yAligned = yPixels / dpi.DpiScaleY;

					double x1 = SeparatorInset;
					double x2 = Math.Max(0, ActualWidth - SeparatorInset);

					var guidelines = new GuidelineSet();
					guidelines.GuidelinesY.Add(yAligned);
					dc.PushGuidelineSet(guidelines);
					dc.DrawLine(pen, new Point(x1, yAligned), new Point(x2, yAligned));
					dc.Pop();
				}
			}
		}

		protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
		{
			base.OnVisualChildrenChanged(visualAdded, visualRemoved);
			InvalidateVisual();
		}

		protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
		{
			base.OnRenderSizeChanged(sizeInfo);
			InvalidateVisual();
		}

		#endregion
	}
}
